﻿//===============================================================================
// Apolineo Patterns & Practices LeanEngine Framework
//===============================================================================
// Copyright © Apolineo Desenvolvimento de Sistemas Ltda.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LeanEngine.SalesConcept.Entity;

using LeanEngine.Extensions;
using LeanEngine.Collections;
using LeanEngine.Business;
using LeanEngine.Data.Linq;

namespace LeanEngine.SalesConcept.Business
{
    //Classe de regra de negócio de produto

    //Aqui herdamos da classe BusinessCrud<T> que implementa todo
    //as operações básicas (inserção, atualização, exclusão, leitura)
    internal sealed class BOProduct : BusinessCrud<Product>
    {
        #region Singleton Members

        private static BOProduct _instance = new BOProduct();

        private BOProduct() { }

        public static BOProduct Instance
        {
            get { return _instance; }
        }

        #endregion

        #region IProduct Members

        public PagedList<Product> ListProducts(ProductSearchCriteria criteria)
        {
            PagedList<Product> pagedList = new PagedList<Product>()
            {
                PageIndex = criteria.PageIndex,
                PageSize = criteria.PageSize
            };

            if (criteria.Color.IsNullOrEmpty())
            {
                SearchProductWithoutColor(criteria, ref pagedList);
            }
            else
            {
                SearchProductWithColor(criteria, ref pagedList);
            }

            return pagedList;
        }

        #endregion

        #region Method Members

        private void SearchProductWithoutColor(ProductSearchCriteria criteria, ref PagedList<Product> pagedList)
        {
            //Aqui utilizamos o provedor linq do lob para fazer uma consulta na tabela de produtos
            //buscando por nome e documento
            using (var ctx = new DatabaseContext())
            {
                //Usamos o método de extensão Coalesce para criar um comando do tipo
                //ISNULL(valor, valor_caso_null) para o SQL Server ou NVL(valor, valor_caso_null)
                var products = from c in ctx.GetTable<Product>()
                                where c.Name.Contains(criteria.Name.Coalesce(c.Name, string.Empty))
                                    && c.QuantityInStock >= criteria.QuantityInStock
                                    && c.YearProduction >= criteria.YearProduction
                                orderby c.Name, c.QuantityInStock
                                select c;

                pagedList = products.GetPage(criteria.PageIndex, criteria.PageSize).ToPagedList();
            }
        }

        private void SearchProductWithColor(ProductSearchCriteria criteria, ref PagedList<Product> pagedList)
        {
            //Aqui utilizamos o provedor linq do lob para fazer uma consulta na tabela de produtos
            //buscando por nome e documento
            using (var ctx = new DatabaseContext())
            {
                //Usamos o método de extensão Coalesce para criar um comando do tipo
                //ISNULL(valor, valor_caso_null) para o SQL Server ou NVL(valor, valor_caso_null)

                //Usamos o método de extensão IsNotNull para criar uma condição VALOR IS NOT NULL
                var products = from c in ctx.GetTable<Product>()
                               where c.Name.Contains(criteria.Name.Coalesce(c.Name, string.Empty))
                                   && c.QuantityInStock >= criteria.QuantityInStock
                                   && c.YearProduction >= criteria.YearProduction
                                   && c.Color.IsNotNull()
                                   && c.Color.Contains(criteria.Color.Coalesce(c.Color, string.Empty))
                               orderby c.Name, c.QuantityInStock
                               select c;

                //O método GetPage executa a consulta paginada e o ToPagedList mapeia do resultado
                //para uma coleção do tipo PagedList<T> (namespace LeanEngine.Collections)
                pagedList = products.GetPage(criteria.PageIndex, criteria.PageSize).ToPagedList();
            }
        }

        #endregion
    }
}
